package org.zjvis.datascience.service.graph;

import lombok.Data;
import org.zjvis.datascience.common.dto.graph.GraphActionDTO;

import java.util.List;
import java.util.Stack;

/**
 * @description GraphActionDeStack
 * @date 2021-12-29
 */
@Data
public class GraphActionDeStack {
    // redo或者undo最大执行次数
    private static final Long MAX_TIMES = 10L;

    private Long graphId;

    private Stack<GraphActionDTO> undoStack;

    private Stack<GraphActionDTO> redoStack;

    public GraphActionDeStack(Long graphId) {
        this.graphId = graphId;
        undoStack = new Stack<>();
        redoStack = new Stack<>();
    }

    /**
     * 从undoStack弹出item入队到redoStack，返回item
     */
    public synchronized GraphActionDTO undo() {
        if (undoStack.isEmpty()) {
            return null;
        }
        GraphActionDTO item = undoStack.pop();
        redoStack.push(item);
        return item;
    }

    /**
     * 从redoStack弹出item，入队到undoStack
     */
    public synchronized GraphActionDTO redo() {
        if (redoStack.isEmpty()) {
            return null;
        }
        GraphActionDTO item = redoStack.pop();
        undoStack.push(item);
        return item;
    }

    public synchronized boolean initUndoStack(GraphActionService graphActionService) {
        List<GraphActionDTO> actions = graphActionService.queryLatestActionByGraphId(graphId, MAX_TIMES * 10);
        undoStack.addAll(actions);
        return true;
    }

    /**
     * 如果在redo和undo的过程中，有做增删改操作，需要去重新更新下undoStack
     */
    public synchronized boolean resizeUndoStack(GraphActionService graphActionService) {
        undoStack.clear();
        return initUndoStack(graphActionService);
    }

    /**
     * 插入数据到undoStack
     * @param action
     * @return
     */
    public synchronized boolean addUndoStack(GraphActionDTO action) {
        undoStack.push(action);
        return true;
    }

    /**
     * 清空redoStack
     * @return
     */
    public synchronized boolean clearRedoStack() {
        redoStack.clear();
        return true;
    }

    /**
     * 撤销栈是否超过限制条数
     * @return
     */
    public int outLimit() {
        return (int) (undoStack.size() - MAX_TIMES);
    }

    /**
     * 移除栈中废弃的一个
     * @return
     */
    public GraphActionDTO removeUndoStack() {
        return undoStack.remove(0);
    }

    public int redoStackSize() {
        return redoStack.size();
    }

    public GraphActionDTO removeRedoStack() {
        return redoStack.remove(0);
    }
}
